package com.zheng.api.server.controller;

import com.alibaba.fastjson.JSONObject;
import com.zheng.api.server.service.ApiServerPayService;
import com.zheng.common.constant.PayConstant;
import com.zheng.common.util.PayCommonUtil;
import com.zheng.common.util.SeqUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Map;

/**
 * @Description: 转账订单
 * @author lvb
 * @date 2017-10-30
 * @version V1.0
 * @Copyright:
 */
@Controller
@Api(value = "商户统一转账控制器", description = "商户统一转账控制器")
@RequestMapping("/v1/pay")
public class ApiPayTransOrderController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ApiPayTransOrderController.class);

    @Autowired
    private ApiServerPayService apiServerPayService;

    /**
     * 统一转账接口:
     * 1)先验证接口参数以及签名信息
     * 2)验证通过创建支付订单
     * 3)根据商户选择渠道,调用支付服务进行下单
     * 4)返回下单数据
     * @param params
     * @return
     */
    @RequestMapping(value = "/trans/create_order")
    @ApiOperation(value = "商户统一转账")
    @ResponseBody
    public String payOrder(@RequestParam String params) {
        LOGGER.info("###### 开始接收商户统一转账请求 ######");
        String logPrefix = "【商户统一转账】";
        try {
            JSONObject po = JSONObject.parseObject(params);
            JSONObject transContext = new JSONObject();
            JSONObject transOrder = null;
            // 验证参数有效性
            Object object = validateParams(po, transContext);
            if (object instanceof String) {
                LOGGER.info("{}参数校验不通过:{}", logPrefix, object);
                return PayCommonUtil.makeRetFail(PayCommonUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, object.toString(), null, null));
            }
            if (object instanceof JSONObject) transOrder = (JSONObject) object;
            if(transOrder == null) return PayCommonUtil.makeRetFail(PayCommonUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付中心转账失败", null, null));
            int result = apiServerPayService.createTransOrder(transOrder);
            LOGGER.info("{}创建转账订单,结果:{}", logPrefix, result);
            if(result != 1) {
                return PayCommonUtil.makeRetFail(PayCommonUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "创建转账订单失败", null, null));
            }
            // 发送异步转账消息
            String transOrderId = transOrder.getString("transorderid");
            String channelName = transContext.getString("channelname");
            apiServerPayService.sendTransNotify(transOrderId, channelName);
            LOGGER.info("{}发送转账任务完成,transOrderId={}", logPrefix, transOrderId);
            Map<String, Object> map = PayCommonUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
            map.put("transorderid", transOrderId);
            return PayCommonUtil.makeRetData(map, transContext.getString("reskey"));
        }catch (Exception e) {
            LOGGER.error("",e);
            return PayCommonUtil.makeRetFail(PayCommonUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付中心系统异常", null, null));
        }
    }

    /**
     * 验证创建订单请求参数,参数通过返回JSONObject对象,否则返回错误文本信息
     * @param params
     * @return
     */
    private Object validateParams(JSONObject params, JSONObject transContext) {
        // 验证请求参数,参数有问题返回错误提示
        String errorMessage;
        // 支付参数
        String mchId = params.getString("mchid"); 			    // 商户ID
        String mchTransNo = params.getString("mchtransno"); 	// 商户转账单号
        String channelId = params.getString("channelid"); 	    // 渠道ID
        String amount = params.getString("amount"); 		    // 转账金额（单位分）
        String currency = params.getString("currency");         // 币种
        String clientIp = params.getString("clientip");	        // 客户端IP
        String device = params.getString("device"); 	        // 设备
        String extra = params.getString("extra");		        // 特定渠道发起时额外参数
        String param1 = params.getString("param1"); 		    // 扩展参数1
        String param2 = params.getString("param2"); 		    // 扩展参数2
        String notifyUrl = params.getString("notifyurl"); 		// 转账结果回调URL
        String sign = params.getString("sign"); 				// 签名
        String channelUser = params.getString("channeluser");	// 渠道用户标识,如微信openId,支付宝账号
        String userName = params.getString("username");	        // 用户姓名
        String remarkInfo = params.getString("remarkinfo");	    // 备注
        // 验证请求参数有效性（必选项）
        if(StringUtils.isBlank(mchId)) {
            errorMessage = "request params[mchid] error.";
            return errorMessage;
        }
        if(StringUtils.isBlank(mchTransNo)) {
            errorMessage = "request params[mchtransno] error.";
            return errorMessage;
        }
        if(StringUtils.isBlank(channelId)) {
            errorMessage = "request params[channelid] error.";
            return errorMessage;
        }
        if(!NumberUtils.isNumber(amount)) {
            errorMessage = "request params[amount] error.";
            return errorMessage;
        }
        if(StringUtils.isBlank(currency)) {
            errorMessage = "request params[currency] error.";
            return errorMessage;
        }
        if(StringUtils.isBlank(notifyUrl)) {
            errorMessage = "request params[notifyurl] error.";
            return errorMessage;
        }
        if(StringUtils.isBlank(channelUser)) {
            errorMessage = "request params[channeluser] error.";
            return errorMessage;
        }
        if(StringUtils.isBlank(remarkInfo)) {
            errorMessage = "request params[remarkinfo] error.";
            return errorMessage;
        }

        // 签名信息
        if (StringUtils.isEmpty(sign)) {
            errorMessage = "request params[sign] error.";
            return errorMessage;
        }

        // 查询商户信息
        JSONObject mchInfo = apiServerPayService.getByMchId(mchId);
        if(mchInfo == null) {
            errorMessage = "Can't found mchInfo[mchid="+mchId+"] record in db.";
            return errorMessage;
        }
        if(mchInfo.getByte("state") != 1) {
            errorMessage = "mchInfo not available [mchid="+mchId+"] record in db.";
            return errorMessage;
        }

        String reqkey = mchInfo.getString("reqkey");
        if (StringUtils.isBlank(reqkey)) {
            errorMessage = "reqkey is null[mchid="+mchId+"] record in db.";
            return errorMessage;
        }
        transContext.put("reskey", mchInfo.getString("reskey"));

        // 查询商户对应的支付渠道
        JSONObject payChannel = apiServerPayService.getByMchIdAndChannelId(mchId, channelId);
        if(payChannel == null) {
            errorMessage = "Can't found payChannel[channelid="+channelId+",mchid="+mchId+"] record in db.";
            return errorMessage;
        }
        if(payChannel.getByte("state") != 1) {
            errorMessage = "channel not available [channelid="+channelId+",mchid="+mchId+"]";
            return errorMessage;
        }
        transContext.put("channelname", payChannel.getString("channelname"));

        // 验证签名数据
        boolean verifyFlag = PayCommonUtil.verifyPaySign(params, reqkey);
        if(!verifyFlag) {
            errorMessage = "Verify XX trans sign failed.";
            return errorMessage;
        }
        // 验证参数通过,返回JSONObject对象
        JSONObject transOrder = new JSONObject();
        transOrder.put("transorderid", SeqUtil.getTrans());
        transOrder.put("mchid", mchId);
        transOrder.put("mchtransno", mchTransNo);
        transOrder.put("channelid", channelId);
        transOrder.put("amount", Long.parseLong(amount));
        transOrder.put("currency", currency);
        transOrder.put("clientip", clientIp);
        transOrder.put("device", device);
        transOrder.put("channeluser", channelUser);
        transOrder.put("username", userName);
        transOrder.put("remarkinfo", remarkInfo);
        transOrder.put("extra", extra);
        transOrder.put("channelmchid", payChannel.getString("channelmchId"));
        transOrder.put("param1", param1);
        transOrder.put("param2", param2);
        transOrder.put("notifyurl", notifyUrl);
        return transOrder;
    }

}
